package ldh.im.fxbase.controller;

import com.jfoenix.controls.JFXButton;
import javafx.application.Platform;
import javafx.embed.swing.SwingFXUtils;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.ScrollEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Rectangle;
import javafx.stage.DirectoryChooser;
import ldh.im.dto.enums.MessageType;
import ldh.im.fxbase.dao.ImMessageDao;
import ldh.im.fxbase.data.pojo.ImMessage;
import ldh.im.fxbase.service.GifViewService;
import ldh.im.fxbase.util.*;
import ldh.im.util.ConfigUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import java.util.ResourceBundle;

/**
 * 图片展示
 */
public class ImagePageController implements Initializable {

    private static final Logger LOGGER = LoggerFactory.getLogger(ImagePageController.class);

//    @FXML private  Group imageMovePane;
    @FXML private ScrollPane imageScrollPane;
    @FXML private StackPane imageContentPane;
    @FXML private TextField imagePathText;
    @FXML private HBox imagePane;
    @FXML private JFXButton nextBtn;
    @FXML private JFXButton beforeBtn;
    @FXML private ImageView imageView;
//    @FXML private Label tip;
    @FXML private Pane root;

    private Rectangle point2D = new Rectangle(0, 0);
    private DirectoryChooser directoryChooser = new DirectoryChooser();
    private ImMessageDao imMessageDao = BeanFactory.getInstance().getBean(ImMessageDao.class);

    private volatile List<ImMessage> messageList = null;
    private int currentPage = 0;
    private int pageSize = 100;
    private volatile int currentIndex = 0;
    private ImMessage imMessage = null;
    private boolean canShowNextOrPre = true;
    private GifViewService gifViewService = null;

    public void setImMessage(ImMessage imMessage, boolean canShowNextOrPre) {
        this.imMessage = imMessage;
        this.canShowNextOrPre = canShowNextOrPre;
        if (gifViewService != null) {
            gifViewService.dispose();
            gifViewService = null;
        }

        nextBtn.setVisible(canShowNextOrPre);
        nextBtn.setManaged(canShowNextOrPre);

        beforeBtn.setVisible(canShowNextOrPre);
        beforeBtn.setManaged(canShowNextOrPre);

        String imagePath = FileUtil.getFilePath(imMessage);
        if (imagePath != null) {
            imagePathText.setText(imagePath.replace(ConfigUtil.getRoot(), ""));
            if (imagePath.toLowerCase().endsWith("gif")) {
                gifViewService = new GifViewService(imagePath);
                Image firstImage = gifViewService.getFirstImage();
                if (firstImage != null) {
                    setImage(firstImage);
                    gifViewService.animateView(imageView);
                }
            } else {
                setImage(new Image(FileUtil.getLocalFilePath(imagePath)));
            }
            LOGGER.debug("imagePath:{}", imagePath);
        } else {
            Image image = new Image(errorPictureUrl().toExternalForm());
            setImage(image);
        }
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        imageView.setOnMousePressed(e->{
            point2D.setX(e.getScreenX());
            point2D.setY(e.getScreenY());
            point2D.setWidth(imageView.getTranslateX());
            point2D.setHeight(imageView.getTranslateY());
        });
        imageView.setOnMouseDragged(e->{
            imageView.setTranslateX(point2D.getWidth() + e.getScreenX() - point2D.getX());
            imageView.setTranslateY(point2D.getHeight() + e.getScreenY() - point2D.getY());
        });

        imageView.setOnScroll(e->{
            scroll(e);
        });

        imagePane.setOnMouseEntered(e->{
            if (canShowNextOrPre) {
                beforeBtn.setVisible(true);
                nextBtn.setVisible(true);
            }

        });
        imagePane.setOnMouseExited(e->{
            if (canShowNextOrPre) {
                beforeBtn.setVisible(false);
                nextBtn.setVisible(false);
            }
        });
        root.setOnScroll(e->scroll(e));

        imageContentPane.widthProperty().addListener(l->{
            fitImage();
        });
        imageContentPane.heightProperty().addListener(l->{
            fitImage();
        });
    }

    // 放大
    public void enlarge() {
        double scale = imageView.getScaleX() + 0.2;
        imageView.setScaleX(scale);
        imageView.setScaleY(scale);
    }

    // 缩小
    public void small() {
        double scale = imageView.getScaleX() - 0.2;
        imageView.setScaleX(scale);
        imageView.setScaleY(scale);
    }

    // 左旋转
    public void rotateLeft() {
        double rotate = imageView.getRotate();
        imageView.setRotate(rotate - 10);
    }

    // 右旋转
    public void rotateRight() {
        double rotate = imageView.getRotate();
        imageView.setRotate(rotate + 10);
    }

    // 下载
    public void download() {
        directoryChooser.setTitle("选择文件夹");
        File dir = directoryChooser.showDialog(StageUtil.getStage().getOwner());
        if (dir == null) return;
        String file = dir + File.separator + System.currentTimeMillis() + ".png";
        File imageFile = new File(file);
        saveImage(imageView.getImage(), imageFile);
    }

    public void setImage(Image image) {
        imageView.setImage(image);
    }

    public void reset() {
        imageView.setScaleY(1.0);
        imageView.setScaleX(1.0);
        imageView.setRotate(0);

        imageView.setTranslateX(0);
        imageView.setTranslateY(0);
    }

    private void scroll(ScrollEvent e) {
        double scale = imageView.getScaleX();
        if (e.getDeltaY() > 0) {
            scale += 0.1;
        } else {
            scale -= 0.1;
        }
        imageView.setScaleX(scale);
        imageView.setScaleY(scale);
    }

    private void saveImage(Image image, File imageFile) {
        BufferedImage bImage = SwingFXUtils.fromFXImage(image, null);
        try {
            ImageIO.write(bImage, "png", imageFile);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @FXML
    private void beforeAct(ActionEvent actionEvent) {
        currentIndex--;
        if (messageList == null || currentIndex < 0) {
            currentIndex = 0;
            loadImagesAndChange(true);
        } else {
            ImMessage imMessage = messageList.get(currentIndex);
            System.out.println("currentIndex:" + currentIndex + ", size:" + messageList.size());
            setImMessage(imMessage, canShowNextOrPre);
        }
    }

    @FXML
    private void nextAct(ActionEvent actionEvent) {
        currentIndex++;
        if (messageList == null || currentIndex >= messageList.size()) {
            loadImagesAndChange(false);
        } else if (currentIndex < messageList.size()){
            ImMessage imMessage = messageList.get(currentIndex);
            System.out.println("currentIndex:" + currentIndex + ", size:" + messageList.size());
            setImMessage(imMessage, canShowNextOrPre);
        }
    }

    private void loadImagesAndChange(boolean isDesc) {
        ThreadPoolUtil.submit(()->{
            try {
                messageList = imMessageDao.getMessagesBySessionId(imMessage.getSessionId(), imMessage.getServerReceiveTime(), Arrays.asList(MessageType.Image), pageSize, isDesc);
                if (!isDesc) currentIndex = 0;
                if (messageList.size() < 1) return;
                if (isDesc) currentIndex = messageList.size()-1;
                ImMessage imMessage = messageList.get(currentIndex);
                Platform.runLater(()->{
                    System.out.println("currentIndex:" + currentIndex + ", size:" + messageList.size());
                    setImMessage(imMessage, canShowNextOrPre);
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

    private URL errorPictureUrl() {
        URL url = this.getClass().getResource("/ldh/im/fxbase/img/error_picture.png");
        if (url == null) {
            url = this.getClass().getResource("/imgs/error_picture.png");
        }
        return url;
    }

    private void fitImage() {
        Image image = imageView.getImage();
        if (image == null) return;
        double imageWidth = image.getWidth();
        double imageHeight = image.getHeight();
        double rootWidth = imageScrollPane.getWidth()-20;
        double rootHeight = imageScrollPane.getHeight()-20;

        if (imageHeight > 0 && rootHeight > 0) {
            if (imageWidth/imageHeight> rootWidth/rootHeight) {
                imageView.setFitWidth(Math.min(imageWidth, rootWidth));
                imageView.setPreserveRatio(true);
            } else {
                imageView.setFitHeight(Math.min(imageHeight, rootHeight));
                imageView.setPreserveRatio(true);
            }
        }

        RegionUtil.centerNodeInScrollPane(imageScrollPane, imageContentPane);
    }
}
